package com.allinace.config;

import com.allinace.handler.FailHandler;
import com.allinace.handler.SessionStrategy;
import com.allinace.handler.SuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.annotation.Resource;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private SuccessHandler successHandler;
    @Resource
    private FailHandler failHandler;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        //httpBasic基本认证模式（容易被破解一般不使用）
//       http.httpBasic()
//               .and()
//               .authorizeRequests().anyRequest().authenticated();

        //formLogin登录认证模式
        http.csrf().disable()
                .formLogin()
                .loginPage("/login.html") //登录页面
                .loginProcessingUrl("/login") //登录认证的处理接口
               // .defaultSuccessUrl("/index") //登录成功跳转接口
               // .failureUrl("/login.html")
                .successHandler(successHandler)//登录成功处理的handler 该配置不能和 defaultSuccessUrl同时存在
                .failureHandler(failHandler)//登录失败处理的handler
                .and().authorizeRequests()
                .antMatchers("/login.html","/login").permitAll()
                .antMatchers("/biz1","/biz2")//对外暴漏的资源路径
                .hasAnyAuthority("ROLE_user","ROLE_admin")//有user和admin权限都可以访问资源路径
                .antMatchers("/syslog")
                .hasAnyRole("admin")//admin角色可以访问
                .antMatchers("/sysuser")
                .hasAnyAuthority("sys:suer")//具有权限id可以请求该资源
                .anyRequest().authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                .invalidSessionUrl("login.html")
                .sessionFixation().migrateSession()
                .maximumSessions(1)//最大session数 防止重复登录
                .maxSessionsPreventsLogin(false)//false表示允许再次登录 之前的登录会被挤下线
                .expiredSessionStrategy(new SessionStrategy());
    }

    /**
     * 配置用户集
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())
                .withUser("user")
                .password(passwordEncoder().encode("123456"))
                .roles("user")
                .and()
                .withUser("admin")
                .password(passwordEncoder().encode("123456"))
                .roles("admin")
                .authorities("sys:user")//给用户分配一个权限id
                .and()
                .passwordEncoder(passwordEncoder());//配置BCrypt加密
    }

    /**
     * 用于用户加密解密
     * 通过bean 注入
     * 用户登录的时候会自动解密
     * @return
     */
    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置静态资源不需要权限认证
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .mvcMatchers("/css/**","/fonts/**","/img/**","/js/**");
    }
}
